package com.siao.core;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author SiaoLeon
 * 线程服务
 */
public abstract class ThreadService implements Runnable {

	private static final Logger logger = LoggerFactory.getLogger("ThreadServer");

	/**
	 * 线程实例
	 */
	protected Thread thread;

	/**
	 * 服务线程名
	 */
	protected String name;

	/**
	 * 服务线程名
	 * @return
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * 服务状态
	 */
	protected ServiceStatus status;

	/**
	 * 服务状态
	 * @return
	 */
	public ServiceStatus getStatus() {
		return this.status;
	}

	/**
	 * 构造函数
	 */
	public ThreadService() {
		this("Thread Server");
	}

	/**
	 * 构造函数
	 */
	public ThreadService(String name) {
		this.name = name;
		this.status = ServiceStatus.STOPPED;
	}

	/**
	 * 服务器初始化
	 * @throws Exception
	 */
	protected abstract void init() throws Exception;

	/**
	 * 执行方法
	 * @throws Exception
	 */
	protected abstract void execute() throws Exception;

	/**
	 * 服务器退出
	 * @throws Exception
	 */
	protected abstract void exit() throws Exception;

	/**
	 * 启动服务器
	 */
	public void start() {
		if (this.status != ServiceStatus.STOPPED) {
			logger.warn(this.name + " is " + this.status + "!");
			return;
		}

		this.thread = new Thread(this, this.name);

		try {
			this.status = ServiceStatus.INITIALIZING;
			this.init();
			this.thread.start();
		} catch (Exception e) {
			logger.error(this.name + " Initializing Failed.");
		}

		this.status = ServiceStatus.RUNNING;
	}

	@Override
	public void run() {
		while (this.status == ServiceStatus.RUNNING) {
			try {
				this.execute();
				Thread.sleep(0L, 10);
			} catch (InterruptedException e) {
				Thread.currentThread().interrupt();
			} catch (Exception e) {
				e.printStackTrace();
				logger.error(this.name + " Execute Failed.");
			}
		}
	}

	/**
	 * 关闭服务器
	 */
	public void stop() {
		if (this.status != ServiceStatus.RUNNING) {
			logger.warn(this.name + " is " + this.status + "!");
			return;
		}

		try {
			this.status = ServiceStatus.STOPPING;
			this.exit();
			this.thread.interrupt();
			this.thread = null;
		} catch (Exception e) {
			logger.error(this.name + " Exit Failed.");
		}

		this.status = ServiceStatus.STOPPED;
	}

}
